package com.ozo.boot.auth.token;

import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.temp.SaTempUtil;
import com.ozo.boot.auth.exception.AuthExceptionEnum;
import com.ozo.boot.auth.pojo.dto.LoginDTO;
import com.ozo.boot.auth.pojo.vo.RefreshTokenVO;
import com.ozo.boot.common.base.model.LoginUser;
import com.ozo.boot.common.core.exception.ServiceException;
import com.ozo.boot.common.satoken.context.UserLoginHelper;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * <p>
 * token生产策略类
 * </p>
 *
 * @author qiangesoft
 * @since 2024-07-11
 */
@Component
public class TokenStore {

    private final Map<String, TokenGranter> GRANTER_POOL = new ConcurrentHashMap<>();

    public TokenStore(Map<String, TokenGranter> tokenGranterMap) {
        this.GRANTER_POOL.putAll(tokenGranterMap);
    }

    private TokenGranter getGranter(LoginType grantType) {
        if (grantType == null) {
            return GRANTER_POOL.get(LoginType.PASSWORD.name());
        }
        TokenGranter tokenGranter = GRANTER_POOL.get(grantType.name());
        if (tokenGranter == null) {
            throw new ServiceException(AuthExceptionEnum.PARAM_GRANT_TYPE_ERROR);
        } else {
            return tokenGranter;
        }
    }

    /**
     * 登录
     * @param loginDTO
     * @return
     */
    public LoginUser login(LoginDTO loginDTO) {
        return this.getGranter(loginDTO.getGrantType()).login(loginDTO);
    }

    /**
     * 退出登录
     * @return
     */
    public void logout() {
        StpUtil.logout();
    }

    /**
     * 刷新token
     * @param refreshToken
     * @return
     */
    public RefreshTokenVO refreshToken(String refreshToken) {
        // 1、验证
        Object userId = SaTempUtil.parseToken(refreshToken);
        if (userId == null) {
            throw new ServiceException(AuthExceptionEnum.PARAM_REFRESH_TOKEN_ERROR);
        }

        // 2、为其生成新的短 token
        StpUtil.login(userId);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();

        // 3、返回
        RefreshTokenVO refreshTokenVO = new RefreshTokenVO();
        refreshTokenVO.setAccessToken(tokenInfo.getTokenValue());
        refreshTokenVO.setExpires(tokenInfo.getTokenTimeout());

        // 长token
        String newRefreshToken = SaTempUtil.createToken(userId, 2592000);
        refreshTokenVO.setRefreshToken(newRefreshToken);

        return refreshTokenVO;
    }

    /**
     * 用户信息
     * @return
     */
    public LoginUser getUserInfo() {
        return UserLoginHelper.getLoginUser();
    }

}
